package com.tplhk.util;

import java.text.ParseException;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.Temporal;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

/**
 * Created by xiao_qiang_01@163.com on 2018/6/9.
 **/
public class DateJdk8Util {
    public static final String yyyyMMDD = "yyyyMMdd";
    public static final String yyyyMM = "yyyyMM";
    public static final String yyyy_MM_dd = "yyyy-MM-dd";
    public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss";
    public static final String yyyy_MM_dd_HH_mm = "yyyy-MM-dd HH:mm";
    public static final String yyyy_MM_dd_T_HH_mm_ss_xxx = "yyyy-MM-dd'T'HH:mm:ssXXX";
    public static final String HH_mm_ss = "HH:mm:ss";
    public static final String ASIA_SHANGHAI = "Asia/Shanghai";
    public static final ZoneId ZONE_ID = ZoneId.systemDefault();


    /**
     * 设置日期时间
     * @return 日期时间,格式 "2017-09-22T10:26:16.268"
     */
    public static LocalDateTime setDateTime(int year, int month, int dayofMonth, int hour, int minute, int second) {
        return  LocalDateTime.of(year, month, dayofMonth, hour, minute, second);
    }

    /**
     * 设置日期
     * @return 日期
     */
    public static LocalDate setDate(int year, int month, int dayofMonth) {
        return  LocalDate.of(year, month, dayofMonth);
    }

    /**
     * 使用默认时区时钟瞬时时间创建
     * @return 日期时间,格式 "2017-09-22T10:26:16.268"
     */
    public static LocalDateTime now() {
        return  LocalDateTime.now();
    }

    /**
     * 使用自定义时区时钟瞬时时间创建
     * @return 日期时间,格式 "2017-09-22T10:26:16.268"
     */
    public static LocalDateTime now(String zoneId) {
        return  LocalDateTime.now(ZoneId.of(zoneId));
    }

    /**
     * 取当前时间的日期字符串
     * @return
     */
    public static String nowToDateTimeStr(String pattern) {
        return localDateTimeToStr(now(), pattern);
    }

    /**
     * 取当前时间的日期字符串
     * @return
     */
    public static String nowToDateTimeStr() {
        return localDateTimeToStr(now(), yyyy_MM_dd_HH_mm_ss);
    }

    /**
     * 取当前时间的日期字符串
     * @return
     */
    public static String nowToDateStr(String pattern) {
        return localDateToStr(LocalDate.now(), pattern);
    }

    public static LocalDate today() {
        return  LocalDate.now();
    }

    /**
     * @return 返回昨天日期
     */
    public static  LocalDate yesterday() {
        return LocalDate.now().minusDays(1);
    }

    /**
     * @return 返回明天日期
     */
    public static  LocalDate tomorrow() {
        return LocalDate.now().plusDays(1);
    }

    /**
     * @return 返回现在{num}天后的时间
     */
    public static  LocalDateTime nowByOffset(int num) {
        return localDateTimeByOffset(LocalDateTime.now(), num);
    }

    /**
     * @return 返回{time}时间 {num}天后的时间
     */
    public static  LocalDateTime localDateTimeByOffset(LocalDateTime localDateTime,int num) {
        return localDateTime.plusDays(num);
    }

    /**
     * 获取字符串时间 加减天数
     * @param dateString
     * @param days
     * @return
     */
    public static String dateStrByOffset(String dateString, int days) {
        LocalDate localDate = dateStrToLocalDate(dateString).plusDays(days);
        return localDateToDateStr(localDate);
    }

    /**
     * 日期时间字符串转对象
     * @param datetimeStr 格式为 "yyyy-MM-dd HH:mm:ss"
     * @return 返回日期时间对像
     */
    public static LocalDateTime datetimeStrToLocalDateTime(String datetimeStr){
        return dateTimeStrToLocalDateTime(datetimeStr, yyyy_MM_dd_HH_mm_ss);
    }

    /**
     * 日期时间字符串转对象
     * @param datetimeStr 带时间的日期字符串
     * @param pattern 自定义格式
     * @return 返回日期时间对像
     */
    public static LocalDateTime dateTimeStrToLocalDateTime(String datetimeStr, String pattern){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDateTime.parse(datetimeStr, formatter);
    }

    /**
     * 日期时间字符串 转 带时区对象
     * @param datetimeStr 带时间的日期字符串
     * @param pattern 自定义格式
     * @return 返回日期时间对像
     */
    public static ZonedDateTime dateTimeStrToZonedDateTime(String datetimeStr, String pattern){
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault());
        return ZonedDateTime.parse(datetimeStr, formatter);
    }

    /**
     * 日期时间字符串转对象
     * @param dateStr 格式为 "yyyy-MM-dd"
     * @return 返回日期时间对像
     */
    public static LocalDate dateStrToLocalDate(String dateStr){
        return dateStrToLocalDate(dateStr, yyyy_MM_dd);
    }

    /**
     * 日期时间字符串转对象
     * @param dateStr 日期字符串
     * @param pattern 自定义格式
     * @return 返回日期时间对像
     */
    public static LocalDate dateStrToLocalDate(String dateStr, String pattern){
        if(null == dateStr){
            return null;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
        return LocalDate.parse(dateStr, formatter);
    }

    /**
     * LocalDateTime 转 LocalDate
     * @param localDateTime
     * @return 返回日期对像
     */
    public static LocalDate localDateTimeToLocalDate(LocalDateTime localDateTime){
        return setDate(localDateTime.getYear(), localDateTime.getMonthValue(), localDateTime.getDayOfMonth());
    }


    /**
     * 日期时间对象 转 日期字符串 (默认转为 yyyy-MM-dd)
     * @param localDateTime
     * @return
     */
    public static String localDateTimeToDateStr(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        return localDateTimeToStr(localDateTime, yyyy_MM_dd);
    }

    /**
     * 日期时间对象 转 时间字符串
     * @param datetime
     * @return
     */
    public static String localDateTimeToTimeStr(LocalDateTime datetime) {
        if (datetime == null) {
            return null;
        }
        return localDateTimeToStr(datetime, HH_mm_ss);
    }

    /**
     * 日期时间字符串转对象
     * @param datetimeStr 格式为 "yyyy-MM-dd HH:mm:ss"
     * @return 返回日期时间字符串 HH:mm:ss
     */
    public static String dateTimeStrToTimeStr(String datetimeStr){
        LocalDateTime localDateTime = datetimeStrToLocalDateTime(datetimeStr);
        return localDateTimeToTimeStr(localDateTime);
    }

    /**
     * 日期时间字符串转对象
     * @param datetimeStr 格式为 "yyyy-MM-dd HH:mm:ss"
     * @return 返回日期时间字符串 yyyy_MM_dd
     */
    public static String dateTimeStrToDateStr(String datetimeStr){
        LocalDate localDateTime = localDateTimeToLocalDate(datetimeStrToLocalDateTime(datetimeStr));
        return localDateToDateStr(localDateTime);
    }

    /**
     * 日期时间对象 转 日期字符串
     * @param localDate
     * @return
     */
    public static String localDateToDateStr(LocalDate localDate) {
        if (localDate == null) {
            return null;
        }
        return localDateToStr(localDate,yyyy_MM_dd);
    }

    /**
     * 日期时间对象转字符串
     * @param datetime 时间日期对象
     * @param pattern 格式化字符串
     * @return 返回格式后的时间日期字符串
     */
    public static String localDateTimeToStr(LocalDateTime datetime, String pattern){
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return dateTimeFormatter.format(datetime);
    }

    /**
     * 日期对象转字符串
     * @param date 时间日期对象
     * @param pattern 格式化字符串
     * @return 返回格式后的时间日期字符串
     */
    public static String localDateToStr(LocalDate date, String pattern){
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(pattern);
        return dateTimeFormatter.format(date);
    }

    /**
     * 获取时间戳毫秒数
     * @return 日期
     */
    public static long localDateTimeToLong (LocalDateTime localDateTime) {
        return  localDateTime.atZone(ZONE_ID).toInstant().toEpochMilli();
    }

    public static String longToDateTimeStr(Long datetime){
        return DateTimeFormatter.ofPattern(yyyy_MM_dd_HH_mm_ss).format(
                LocalDateTime.ofInstant(Instant.ofEpochMilli(datetime), ZoneId.systemDefault()));
    }



    public static List<String> lastQuarter() {
        Calendar startCalendar = Calendar.getInstance();
        startCalendar.set(Calendar.MONTH, (startCalendar.get(Calendar.MONTH) / 3 - 1) * 3);
        LocalDate localDate3MonthAgo = LocalDateTime.ofInstant(startCalendar.toInstant(), startCalendar.getTimeZone().toZoneId()).toLocalDate();

        List<String> result = new LinkedList<>();
        result.add(DateJdk8Util.localDateToStr(localDate3MonthAgo, "yyyyMM"));
        result.add(DateJdk8Util.localDateToStr(localDate3MonthAgo.plusMonths(1L), "yyyyMM"));
        result.add(DateJdk8Util.localDateToStr(localDate3MonthAgo.plusMonths(2L), "yyyyMM"));
        return result;
    }

    /**
     * 返回两个日期之间的间隔多少年月日
     * @param date1
     * @param date2
     * @return
     */
    public static Period periodBeteen(LocalDate date1, LocalDate date2) {
        return Period.between(date1,date2);
    }
    /**
     * 返回两个日期之间的间隔多少天，小时，分钟，秒
     * @param date1 必须带时间，可以是 LocalDateTime 或 LocalTime
     * @param date2 必须带时间，可以是 LocalDateTime 或 LocalTime
     * @return
     */
    public static Duration durationBeteen(Temporal date1, Temporal date2) {
        return Duration.between(date1,date2);
    }


    /*****************************************************************************************************************
     * ***************************************************************************************************************
     * *******************    Date 与 java8 Date 互相转换   **********************************************************
     * ***************************************************************************************************************
     */

    /**
     * java.util.Date --> java.time.LocalDateTime
     */
    public static LocalDateTime dateToLocalDateTime(Date date) {
        Instant instant = date.toInstant();
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }

    /**
     * java.util.Date --> java.time.LocalDate
     */
    public static LocalDate dateToLocalDate(Date date) {
        Instant instant = date.toInstant();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return localDateTime.toLocalDate();
    }
    /**
     * java.util.Date --> java.time.LocalTime
     */
    public static LocalTime dateToLocalTime(Date date) {
        Instant instant = date.toInstant();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
        return localDateTime.toLocalTime();
    }
    /**
     * java.time.LocalDateTime --> java.util.Date
     */
    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    /**
     * java.time.LocalDate --> java.util.Date
     */
    public static Date localDateToDate(LocalDate localDate) {
        Instant instant = localDate.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    /**
     * 根据生日获取年龄
     *
     * @param birthDay
     * @return
     */
    public static int getAge(Date birthDay) {
        try {
            Calendar cal = Calendar.getInstance();
            if (cal.before(birthDay)) {
                return 0;
            }
            int yearNow = cal.get(Calendar.YEAR);
            int monthNow = cal.get(Calendar.MONTH);
            int dayOfMonthNow = cal.get(Calendar.DAY_OF_MONTH);
            cal.setTime(birthDay);
            int yearBirth = cal.get(Calendar.YEAR);
            int monthBirth = cal.get(Calendar.MONTH);
            int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH);
            int age = yearNow - yearBirth;
            if (monthNow <= monthBirth) {
                if (monthNow == monthBirth) {
                    if (dayOfMonthNow < dayOfMonthBirth) {
                        age--;
                    }
                } else {
                    age--;
                }
            }
            return age;
        } catch (Exception e) {
            return 0;
        }
    }



    public static void main(String[] args) throws ParseException {
//计算两个Temporal对象的时间差
//        LocalDate date1 = LocalDate.of(2017,8,1);
//        LocalDate date2 = LocalDate.now();
//        Period period = Period.between(date1,date2);
//        System.out.println("date1: "+date1+"\ndate2: "+date2);
//        System.out.println("Period->years:"+period.getYears()+" months:"+period.getMonths()+" days:"+period.getDays());
//        System.out.println("Duration->" +period.toTotalMonths());
//        period.getUnits().forEach( temporalUnit -> System.out.print(temporalUnit+": "+period.get(temporalUnit)+" ") );
//        System.out.println("\"----------------------\" = " + "----------------------");
//        LocalDateTime tdate1 = LocalDateTime.of(2017,9,20,0,0,0);
//        LocalDateTime tdate2 = LocalDateTime.now();
//        LocalTime time1 = LocalTime.of(0,0,0);
//        LocalTime time2 = LocalTime.now();
//        System.out.println("time1: "+time1+"\ntime2: "+time2);
//        Duration duration = Duration.between(tdate1,tdate2);
//        System.out.println("duration.toHours() = " + duration.toHours());
//        System.out.println(localDateTimeFormatter(now(), "yyyy-MM-dd-HH"));
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        sdf.setTimeZone(TimeZone.getTimeZone("GMT+8"));
//        String synTime = sdf.format(Long.parseLong("1528517700224"));
//        System.out.println("BornTimestamp:"  + "____" + synTime);
//        System.out.println("BornTimestamp. " +
//                longToDateTimeStr(Long.valueOf("1528517700224"))
//        );
//
//
//        getLastQuarter().stream().forEach(item -> System.out.println(item));
        String a = "2021-12-06 12:12:12";

        System.out.println(dateTimeStrToDateStr(a));

    }




}
